package com.nulldev.util.threading.v2;

import com.nulldev.util.threading.v3.Worker;

public class nThread implements Runnable{

	private Runnable r;
	private SafeRunnable sr;
	private String id;
	private ThreadPriority priority;
	private ThreadExecution execution;
	private ThreadMode mode;
	private boolean done = false;

	public nThread(final Runnable r) {
		this.r = r;
		this.id = "$generic";
		this.priority = ThreadPriority.DELAYABLE;
		this.execution = ThreadExecution.NORMAL;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final Runnable r, final String id) {
		this.r = r;
		this.id = id;
		this.priority = ThreadPriority.DELAYABLE;
		this.execution = ThreadExecution.NORMAL;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final Runnable r, final String id, final ThreadPriority priority) {
		this.r = r;
		this.id = id;
		this.priority = priority;
		this.execution = ThreadExecution.NORMAL;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final Runnable r, final String id, final ThreadPriority priority, final ThreadExecution execution) {
		this.r = r;
		this.id = id;
		this.priority = priority;
		this.execution = execution;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final Runnable r, final String id, final ThreadPriority priority, final ThreadExecution execution, final ThreadMode mode) {
		this.r = r;
		this.id = id;
		this.priority = priority;
		this.execution = execution;
		this.mode = mode;
	}
	
	public nThread(final SafeRunnable r, final String id) {
		this.sr = r;
		this.id = id;
		this.priority = ThreadPriority.DELAYABLE;
		this.execution = ThreadExecution.NORMAL;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final SafeRunnable r, final String id, final ThreadPriority priority) {
		this.sr = r;
		this.id = id;
		this.priority = priority;
		this.execution = ThreadExecution.NORMAL;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final SafeRunnable r, final String id, final ThreadPriority priority, final ThreadExecution execution) {
		this.sr = r;
		this.id = id;
		this.priority = priority;
		this.execution = execution;
		this.mode = ThreadMode.NORMAL;
	}

	public nThread(final SafeRunnable r, final String id, final ThreadPriority priority, final ThreadExecution execution, final ThreadMode mode) {
		this.sr = r;
		this.id = id;
		this.priority = priority;
		this.execution = execution;
		this.mode = mode;
	}

	public Runnable task() {
		return this.r;
	}
	
	public SafeRunnable task_safe() {
		return this.sr;
	}

	public void updateTask(final Runnable newTask) {
		this.r = newTask;
	}
	
	public void updateTask(final SafeRunnable newTask) {
		this.sr = newTask;
	}

	public String id() {
		return this.id;
	}

	public void updateID(final String newID) {
		this.id = newID;
	}

	public ThreadPriority priority() {
		return this.priority;
	}

	public void updatePriority(final ThreadPriority newPriority) {
		this.priority = newPriority;
	}

	public ThreadExecution execution() {
		return this.execution;
	}

	public void updateExecution(final ThreadExecution newExecution) {
		this.execution = newExecution;
	}

	public ThreadMode mode() {
		return this.mode;
	}

	public void updateMode(final ThreadMode newMode) {
		this.mode = newMode;
	}

	@Override
	public void run() {
		this.done = false;
		if (this.r != null) {
			this.r.run();
		}else if (this.sr != null) {
			try {
				this.sr.run();
			}catch (Exception e) {
				this.sr.onException(e);
			}
		}
		this.done = true;
	}
	
	public void end() {
		this.done = true;
	}

	public boolean done() {
		return this.done;
	}

	private boolean exec = false;
	public void setExecuted(final boolean executed) {
		this.exec = executed;
	}
	
	public boolean isExecuted() {
		return this.exec;
	}

	/**
	 * Converts nThread to IWorker, allowing forward support with threadIt! v3. <br>
	 * Expected Usage: new ThreadDispatcher().addTask(x); (Please store ThreadDispatcher as a variable)
	 * @returns IWorker
	 */
	public Worker toWorker() {
		return new Worker() {
			
			@Override
			public String getName() {
				return nThread.this.id;
			}
			
			@Override
			public void execute() {
				nThread.this.run();
			}
		};
	}
}
